﻿/**********************
*author: LiQingMing
*time: 2018/8/30 19:51:49
*desc:   
**********************/

using LogSystem;
using System;
using System.Collections.Generic;
using UnityEngine;
using Yoozoo.Managers.ResourceManagerV2.Framework.Resource;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Object = UnityEngine.Object;

namespace Yoozoo.Mars.Got
{
    public class SpriteData
    {
        public Sprite sprite;
        public Sprite changeColorSprite1;
        public Sprite changeColorSprite2;
        public List<Sprite> changeColorSprites = new List<Sprite>();
        public List<Vector2> offsets = new List<Vector2>();
        public Vector2 startOffset;
        public Rect changeColorUV;
        public Vector2 offset1;
        public Vector2 offset2;

        public Vector2 GetOffset(int index)
        {
            if (offsets.Count > index)
            {
                return offsets[index];
            }
            return Vector2.zero;
        }
    }
    
    public class SpriteAnimationAction
    {
        public string actionName;
        public Dictionary<int, Dictionary <int,SpriteData>> directionSpList;

        public SpriteAnimationAction(string actionName)
        {
            this.actionName = actionName;
            directionSpList = new  Dictionary<int, Dictionary <int,SpriteData>>(8);
        }
    }

    /// <summary>
    /// 一个小兵一个
    /// </summary>
    public class SpriteAnimationX
    {
        public Texture2D texture;
        public string assetName;

        public int totalFrameCount;
        // 方向-->List<Sprite>
        public Dictionary<string, SpriteAnimationAction> actions;

        public float scale;
        //一个兵种： key是动作

        public string SoldierName;//内城展示用
        public string SoldierLevel;//内城展示用
        public SpriteAnimationX(string assetName)
        {
            this.assetName = assetName;
            actions = new Dictionary<string, SpriteAnimationAction>(8);
        }
    }
    

    public class BaseSpriteCache
    {
        protected static BaseSpriteCache m_instance;
        protected List<string> m_resNames;
        protected Dictionary<string, SpriteAnimationX> m_cacheX;
        private Dictionary<string, bool> hasAdd2LoadSpriteMap;
        protected int m_loadIndex;
        protected bool m_loadComplete = false;
        protected Action m_loadCompleteCallBack;

        private Dictionary<string, List<Action>> spriteLoadOverAction;

        public bool LoadComplete
        {
            get { return m_loadComplete; }

            set { m_loadComplete = value; }
        }

        public BaseSpriteCache()
        {
            m_cacheX = new Dictionary<string, SpriteAnimationX>(16);
            hasAdd2LoadSpriteMap = new Dictionary<string, bool>(16);
            spriteLoadOverAction = new Dictionary<string, List<Action>>(16);
            Init();
        }

        public virtual void Init()
        {

        }

        private const int defaultMaskCount = 2;
        
        public static Dictionary<string,int> specialMaskCountSprite = new Dictionary<string, int>
        {
            ["gta_innercity_truck_01"] = 5,
        };

        private void ApplyMaskOffset(SpriteAnimationX sax)
        {
            foreach (var action in sax.actions)
            {
                foreach (var item in action.Value.directionSpList)
                {
                    foreach (var it in item.Value)
                    {
                        var item2 = it.Value;
                        if (item2.sprite)
                        {
                            var rect = item2.sprite.rect;
                            var xOffset = item2.sprite.pivot.x + rect.x;
                            var yOffset = item2.sprite.pivot.y + rect.y;
                            //（原图的uv - 原图的左下角uv) + 换色左下角uv = 换色的uv
                            item2.startOffset = new Vector2(xOffset / sax.texture.width, yOffset / sax.texture.height);
                            for (int i = 0; i < item2.changeColorSprites.Count; i++)
                            {
                                var sprite = item2.changeColorSprites[i];
                                rect = sprite.rect;
                                var xOffset2 = sprite.pivot.x + rect.x;
                                var yOffset2 = sprite.pivot.y + rect.y;
                                item2.offsets.Add(new Vector2((xOffset2 - xOffset) / sax.texture.width,(yOffset2 - yOffset) / sax.texture.height));
                                if (i == 0)
                                {
                                    var positionUV = new Vector2((item2.sprite.pivot.x - sprite.pivot.x + item2.sprite.rect.x) / sax.texture.width,
                                        (item2.sprite.pivot.y - sprite.pivot.y + item2.sprite.rect.y) / sax.texture.height);
                                    var sizeUV = new Vector2(sprite.rect.width / sax.texture.width,
                                        sprite.rect.height / sax.texture.height);
                                    item2.changeColorUV = new Rect(positionUV,sizeUV);
                                }
                            }
                        }
                    }
                }
            }
        }

        private object soldierAtlasAsset;

        private void OnSoldierAtlasLoadFinish(object asset,string assetName,string atlasName)
        {
            try
            {
                //UnityEngine.Debug.Log($"OnSoldierAtlasLoadFinish: asset = {asset}, assetName = {assetName}");
                
                if (m_cacheX.ContainsKey(assetName))
                {
                    UMTResource.UnloadAsset(asset);
                    return;
                }

                soldierAtlasAsset = asset;
                var sax = new SpriteAnimationX(assetName);
                m_cacheX.Add(atlasName, sax);
                object[] allSubAssets = UMTResource.GetAllSubAssets(asset);

                // 获取精灵的数量
                int startIndex = 0;
                if (allSubAssets[0] is Texture2D)
                {
                    startIndex = 1;
                }
                
                Sprite firstSprite = null;
                Sprite tmpSprite;
                int _fi = 0;
                bool isJeep = assetName.Contains("jeep");
				bool isInnerCitySoldier = assetName.ToLower().Contains("tex_soilder_idle");
                //UnityEngine.Debug.Log($"OnSoldierAtlasLoadFinish: subAssets = {allSubAssets.Length}");
                for (int i = startIndex; i < allSubAssets.Length; i++)
                {
                    //UnityEngine.Debug.Log($"subAssets[{i}] = {allSubAssets[i]}");
                    tmpSprite = allSubAssets[i] as Sprite;
                    if (tmpSprite)
                    {
                        // 创建动画对象
                        if (sax.texture == null)
                        {
                            sax.texture = tmpSprite.texture;
                        }

                        // 序列帧命名协议： 动作-方向-帧数
                        string[] names = tmpSprite.name.Split('-');
                        string actionName;
                        int frame = 0;
                        int dir = 0;
                        int changeSpriteType = 0;
						if (isInnerCitySoldier)
                    	{
                        	actionName = names[0] + names[1];
                        	dir = 1;
                        	if (names.Length == 4)
                        	{
                            	int.TryParse(names[3], out frame);
                            	_fi++;
                        	}
                        	else
                        	{
                            	int.TryParse(names[4], out frame);
                            	changeSpriteType = 1;
                        	}
                        
                        	if (frame != 0 && !isJeep) //防止帧数是从0开始命名的
                        	{
                            	frame = frame - 1;
                        	}
                    	}
						else
						{
						
                        if (names.Length == 4)
                        {
                            actionName = names[1];
                            int.TryParse(names[2], out dir);
                            dir = dir - 1;
                            int.TryParse(names[3].Split('(')[0], out frame);
                            if (frame != 0 && !isJeep) //防止帧数是从0开始命名的
                            {
                                frame = frame - 1;
                            }

                            if (names[0] == "mask")
                            {
                                changeSpriteType = 1;
                            }
                            else if (names[0] == "mask1")
                            {
                                changeSpriteType = 2;
                            }
                            else if (names[0] == "mask2")
                            {
                                changeSpriteType = 3;
                            }
                            else if (names[0] == "mask3")
                            {
                                changeSpriteType = 4;
                            }
                            else
                            {
                                _fi++;
                            }
                        }
                        else
                        {
                            actionName = names[0];
                            int.TryParse(names[1], out dir);
                            dir = dir - 1;
                            int.TryParse(names[2].Split('(')[0], out frame);
                            if (frame != 0 && !isJeep) //防止帧数是从0开始命名的
                            {
                                frame = frame - 1;
                            }

                            _fi++;
                        }

						}
                        
                        //方向
                        SpriteAnimationAction spriteAnimAction;
                        if (!sax.actions.TryGetValue(actionName, out spriteAnimAction))
                        {
                            spriteAnimAction = new SpriteAnimationAction(actionName);
                            sax.actions.Add(actionName, spriteAnimAction);
                        }

                        //帧
                        Dictionary<int, SpriteData> spriteList;
                        if (!spriteAnimAction.directionSpList.TryGetValue(dir, out spriteList))
                        {
                            spriteList = new Dictionary<int, SpriteData>();
                            spriteAnimAction.directionSpList.Add(dir, spriteList);
                        }

                       
                        var sprite = (Sprite)allSubAssets[i];//UnityEngine.Object.Instantiate((Sprite) allSubAssets[i]);
                        if (!spriteList.ContainsKey(frame))
                        {
                            spriteList.Add(frame, new SpriteData());
                        }
                        if (changeSpriteType != 0)
                        {
                            var insertIndex = changeSpriteType - 1;
                            var originCount = spriteList[frame].changeColorSprites.Count;
                            if (originCount > insertIndex)
                            {
                                spriteList[frame].changeColorSprites[insertIndex] = sprite;
                            }
                            else
                            {
                                for (int k = 0; k <= insertIndex - originCount; k++)
                                {
                                    spriteList[frame].changeColorSprites.Add(null);
                                }
                                spriteList[frame].changeColorSprites[insertIndex] = sprite;
                            }
                        }
                        else
                        {
                            spriteList[frame].sprite = sprite;
                            //由于显示的大小会根据第一个精灵的大小来进行缩放，所以要找到第一个精灵
                            if (firstSprite == null)
                            {
                                firstSprite = tmpSprite;
                            }
                            else if (string.Compare(firstSprite.name, tmpSprite.name, StringComparison.Ordinal) > 0)
                            {
                                firstSprite = tmpSprite;
                            }
                        }
                    }
                }

                if (sax != null)
                {
                    sax.totalFrameCount = _fi;
                    if (firstSprite != null)
                    {
                        sax.scale = firstSprite.textureRect.width / 57f; //, firstSprite.textureRect.height) / 57f;
                    }
                    else
                    {
                        sax.scale = 1;
                    }
                }
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError(e.StackTrace);
                throw;
            }
        }
        
        public virtual void LoadSoldierAtlas(string atlasName, Action loadComplete)
        {
            string assetPath = "Assets/ResourcesAssets/FrameAnimation/tex_" + atlasName + ".png";
            UMTResource.LoadAsset(assetPath, (name, asset, duration, data) =>
            {
                OnSoldierAtlasLoadFinish(asset, name, atlasName);
                ApplyMaskOffset(m_cacheX[atlasName]);
                loadComplete?.Invoke();
                if (spriteLoadOverAction.TryGetValue(atlasName, out var list))
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        list[i].Invoke();
                    }
                    list.Clear();
                }
            }, (name, status, message, data) =>
            {
                Debug.Log(LogModule.Sandbox, $"LoadSoldierAtlas failed: {name}");
            });
        }

        public void AddLoadFinishAction(string atlasName,Action action)
        {
            if (action == null)
            {
                return;
            }
            //先判断下资源是否已经加载回来了
            if (m_cacheX.ContainsKey(atlasName))
            {
                action.Invoke();
                return;
            }
            if (!spriteLoadOverAction.TryGetValue(atlasName, out var list))
            {
                list = new List<Action>();
                spriteLoadOverAction.Add(atlasName,list);
            }
            list.Add(action);
        }

        public virtual bool hasCache(string altasPath)
        {
            return m_cacheX.ContainsKey(altasPath);
        }

        public virtual bool HasAdd2LoadSprite(string altasPath)
        {
            return hasAdd2LoadSpriteMap.ContainsKey(altasPath);
        }
        public virtual void Add2Load(string altasPath)
        {
            hasAdd2LoadSpriteMap.Add(altasPath,true);
        }

        public virtual void getSprites(string altasPath, out SpriteAnimationX sps)
        {
            sps = m_cacheX[altasPath];
        }

        public virtual void Clean()
        {
            if (soldierAtlasAsset != null)
                UMTResource.UnloadAsset(soldierAtlasAsset);
            m_cacheX.Clear();
            hasAdd2LoadSpriteMap.Clear();
            m_loadComplete = false;
            m_loadCompleteCallBack = null;
            spriteLoadOverAction.Clear();
        }
    }
}
